<template>
  <div class="container" ref="container">
    <div class="box"></div>
  </div>
</template>
<script setup lang="ts">
import * as THREE from 'three'
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'
// 引入性能监视器
import Stats from 'three/examples/jsm/libs/stats.module.js'
// 导入动画库
import gsap from 'gsap'
// 导入dat.gui
import * as dat from 'dat.gui'

import { onMounted, ref } from 'vue'
// import { RouterLink, RouterView } from 'vue-router'

const container: any = ref(null)
// 创建性能监视器
const stats = new (<any>Stats)()

// 创建场景
const scene = new THREE.Scene()
scene.background = new THREE.Color('rgb(0,47,167)')

// 创建相机
const camera = new THREE.PerspectiveCamera(
  100,
  window.innerWidth / (window.innerHeight - 1),
  0.1,
  1000
)
// 默认情况下，当我们调用scene.add()的时候，物体将会被添加到(0,0,0)坐标。
// 但将使得摄像机和立方体彼此在一起。为了防止这种情况的发生，我们只需要将摄像机稍微向外移动一些即可。
camera.position.set(0, 10, 100)

// 坐标网格
const gridHelper = new THREE.GridHelper(
  1000,
  100,
  new THREE.Color('#F7F7F7'),
  new THREE.Color('#F7F7F7')
)
scene.add(gridHelper)

// 创建渲染器
const renderer = new THREE.WebGLRenderer({
  precision: 'highp', //着色器精度
  antialias: true //抗锯齿
})
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight - 1)

// 轨道控制器
const orbitControls = new OrbitControls(camera, renderer.domElement)
orbitControls.update()

function animate() {
  requestAnimationFrame(animate)
  renderer.render(scene, camera)
  stats.update()
  orbitControls.update()
}

// 画面尺寸变化
window.addEventListener('resize', () => {
  console.log('尺寸变化')
  // 摄像机视锥体的长宽比，通常是使用画布的宽/画布的高。默认值是1（正方形画布）。
  camera.aspect = window.innerWidth / (window.innerHeight - 1)
  camera.updateProjectionMatrix()
  //渲染器宽高比
  renderer.setSize(window.innerWidth, window.innerHeight - 1)
  renderer.setPixelRatio(window.devicePixelRatio)
})

// 1、创建一个空的几何体对象
const geometry = new THREE.BufferGeometry()
// 2、类型化数组创建顶点数据
const vertices = new Float32Array([
  0,
  0,
  0, //顶点1坐标
  50,
  0,
  0, //顶点2坐标
  0,
  100,
  0, //顶点3坐标
  0,
  0,
  0, //顶点4坐标
  0,
  0,
  100, //顶点5坐标
  50,
  0,
  0 //顶点6坐标
])

/**
 * 创建点
 */
// 创建属性缓冲区对象
const attribute = new THREE.BufferAttribute(vertices, 3) //3个为一组，表示一个顶点的xyz坐标
//  设置几何体attributes属性的position位置属性
geometry.attributes.position = attribute
// 创建点材质
const pointsMaterial = new THREE.PointsMaterial({
  color: 0xff0000,
  size: 5 //设置点的大小
})
// 几何体geometry作为点模型Points参数，会把几何体渲染为点
const point = new THREE.Points(geometry, pointsMaterial)
// 添加到场景中
scene.add(point)

/**
 * 创建线
 */
// 线材质对象
const lineBasicMaterial = new THREE.LineBasicMaterial({
  color: 0xffff00
})
// 线模型对象
const line = new THREE.Line(geometry, lineBasicMaterial)
// 闭合线条,最终形成一个闭环
// const line = new THREE.LineLoop(geometry, lineBasicMaterial)
// 非闭合线条，每两个点连一条线
// const line = new THREE.LineSegments(geometry, lineBasicMaterial)
scene.add(line)

/**
 * 创建面
 * 面的可见性默认是单向的
 * 坐标逆时针：正面
 * 坐标顺时针：反面
 * 
  THREE.FrontSide	正面（默认）
  THREE.BackSide	反面
  THREE.DoubleSide	双面
 */
// 面材质对象
const meshBasicMaterial = new THREE.MeshBasicMaterial({
  color: 0xff00ff,
  // side: THREE.BackSide,
  side: THREE.DoubleSide
})
// 面模型对象
const mesh = new THREE.Mesh(geometry, meshBasicMaterial)
scene.add(mesh)

// 页面挂载后渲染
onMounted(() => {
  console.log(container.value)
  container.value?.appendChild(renderer.domElement)
  container.value?.appendChild(stats.domElement) //性能监视器
  animate()
})
</script>
<style scoped>
.box {
  width: 100px;
  height: 100px;
  position: absolute;
}
</style>
